package cloud.hedou.abp.remote

import cloud.hedou.abp.auth.CurrentUser
import cloud.hedou.abp.identity.RemoteIdentityService
import cloud.hedou.abp.starter.AbpContext
import okhttp3.Interceptor
import okhttp3.Response
import java.net.HttpURLConnection

class HeadersInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request().newBuilder().addHeader("Accept", "application/json").build()

        // 添加当前用户的请求头
        if (request.headers().get(HEADER_AUTHORIZATION).isNullOrEmpty()) {
            val token = CurrentUser.token
            if (!token.isNullOrEmpty()) {
                request = request.newBuilder().addHeader(HEADER_AUTHORIZATION, token).build()
            }
        }

        // 如果请求头中没有授权信息，则添加本服务注册到的授权信息
        if (request.headers().get(HEADER_AUTHORIZATION).isNullOrEmpty()) {
            val serverToken = AbpContext.serverToken
            if (!serverToken.isNullOrEmpty()) {
                request = request.newBuilder().addHeader(HEADER_AUTHORIZATION, serverToken).build()
            }
        }

        // 如果没有租户信息
        if (request.headers().get(HEADER_TENANT).isNullOrEmpty()) {
            val tenantId = CurrentUser.tenantId
            if (tenantId.isNotEmpty()) {
                request = request.newBuilder()
                    .addHeader(HEADER_TENANT, tenantId)
                    .url(request.url().newBuilder().addQueryParameter("__tenant", tenantId).build())
                    .build()
            }
        }

        // 发送请求
        var response = chain.proceed(request)

        // 如果返回了401，则尝试刷新token
        if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
            val accessToken = try {
                AbpContext.getBean<RemoteIdentityService>().register()
            } catch (throwable: Throwable) {
                null
            }
            if (!accessToken.isNullOrEmpty()) {
                //如果获取到了新的token，则构建一个新的请求，再次发起
                AbpContext.serverToken = accessToken
                request = request.newBuilder()
                    .removeHeader(HEADER_AUTHORIZATION)
                    .addHeader(HEADER_AUTHORIZATION, "Bearer $accessToken")
                    .build()
                response.close()
                response = chain.proceed(request)
            }
        }
        return response
    }

    companion object {

        private const val HEADER_TENANT = "__tenant"
        private const val HEADER_AUTHORIZATION = "authorization"

    }

}